#pragma once
#include "base/function.hpp"
#include "base/noncopyable.h"
#include "base/config.h"
#include "net/socket.h"

#include <atomic>
#include <string>
#include <vector>
namespace net_tools{
class Count_down_cond;
class Eventloop;
class Logthread;
namespace net{
class Accept;
class Connect;
} // namespace net
namespace base{
class Timeevent;
} // namespace base
class Eventloopthreadpool;
class Tcpserver : net_tools::base::noncopyable{
 public:
  Tcpserver();
  ~Tcpserver(){};
  void Initserver(int thread_number = 0,
                  int work_thread_number = _C::WORK_THREAD_POOL_SIZE,
                  int mempool_block_number = _C::BUFFER_MEMPOOL_BLOCK_NUMBER,
                  int mempool_block_size = _C::BUFFER_MEMPOOL_BLOCK_SIZE,
                  std::string name = std::string("SERVER MAIN THREAD"));
  void Startserver(int port = _C::DEFAULT_PORT);
  int Get_connect_number();

  inline void Set_cpu_high_level_todo(func cb){cpu_high_level_callback_ = std::move(cb);};
  inline void Set_before_loop_todo(eventloop_func cb){before_loop_todo_ = std::move(cb);};

  inline void Set_connect_over_callback(connect_func cb){connect_over_callback_ = std::move(cb);};
  void Add_timejob(const std::string job_name,func todo,timeval begin_time,timeval time,int count);
  void Add_timejob_after_sec(const std::string job_name,func todo,long int begin_after,long int sec,int count);
  void Del_timejob(const std::string job_name);
  net_tools::base::Timeevent* Add_once_timejob_at(func func_,timeval begin_time);
  net_tools::base::Timeevent* Add_once_timejob_after(func func_,timeval begin_time);
  net_tools::base::Timeevent* Add_once_timejob_after_sec(func func_,long int sec);
  bool Del_once_timejob(net_tools::base::Timeevent* timeevent);

 private:
  void New_connect(Eventloop* eventloop,sockaddr_in new_connect_addr,int new_connect_fd);
  void New_connect_call_back();

  static void Default_thread(Eventloop* eventloop,eventloop_func before_loop_todo,connect_func lose_callback,Count_down_cond* count_down_cond);

  static void Default_message(net::Connect* connect);
  static void Default_close(net::Connect* connect);
  static void Default_lose(net::Connect* connect);
  static void Default_user_close(net::Connect* connect);

  Count_down_cond*                    count_down_cond_;
  int                                 thread_number_;
  std::vector<net_tools::Eventloop*>* eventlooppool_;
  Eventloopthreadpool*                eventloopthreadpool_;
  Eventloop*                          eventloop_;
  net::Accept*                        accept_;
  int                                 accept_fd;
  socklen_t                           sockaddr_in_size;
  static std::atomic<int>             connect_number_;

  func           cpu_high_level_callback_;
  eventloop_func before_loop_todo_;
  eventloop_func thread_todo;
  connect_func   connect_over_callback_;

  connect_func   message_callback_;
  connect_func   close_callback_;
  connect_func   lose_callback_;
};

} // namespace net_tools